package edu.ualberta.med.biobank.dialogs; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; import javax.mail.AuthenticationFailedException; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import edu.ualberta.med.biobank.BiobankPlugin; import edu.ualberta.med.biobank.SessionManager; import edu.ualberta.med.biobank.gui.common.BgcPlugin; import edu.ualberta.med.biobank.gui.common.dialogs.BgcBaseDialog; import edu.ualberta.med.biobank.gui.common.validators.NonEmptyStringValidator; import edu.ualberta.med.biobank.gui.common.widgets.BgcBaseText; import edu.ualberta.med.biobank.gui.common.widgets.BgcBaseWidget; import edu.ualberta.med.biobank.preferences.PreferenceConstants; import edu.ualberta.med.biobank.utils.EMailDescriptor; public class SendErrorMessageDialog extends BgcBaseDialog { private static final String CONTENT_TYPE = "text/plain"; private static final String MAIL_SMTP_SOCKET_FACTORY_FALLBACK_KEY = "mail.smtp.socketFactory.fallback"; private static final String MAIL_SMTP_SOCKET_FACTORY_CLASS_KEY = "mail.smtp.socketFactory.class"; private static final String MAIL_SMTP_SOCKET_FACTORY_PORT_KEY = "mail.smtp.socketFactory.port"; private static final String MAIL_SMTP_PORT_KEY = "mail.smtp.port"; private static final String MAIL_SMTP_AUTH_KEY = "mail.smtp.auth"; private static final String MAIL_SMTP_HOST_KEY = "mail.smtp.host"; private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; private EMailDescriptor email; private List<AttachmentComposite> attachments; public SendErrorMessageDialog(Shell parentShell) { super(parentShell); initEmailDescriptor(); attachments = new ArrayList<AttachmentComposite>(); } @Override protected String getTitleAreaMessage() { return "Please describe steps to reproduce the problem. The application error log will be automatically attached."; } @Override protected String getTitleAreaTitle() { return "Send Error EMail"; } @Override protected Image getTitleAreaImage() { return BgcPlugin.getDefault().getImageRegistry() .get(BgcPlugin.IMG_EMAIL_BANNER); } @Override protected int getTitleAreaMessageType() { return IMessageProvider.INFORMATION; } @Override protected void createDialogAreaInternal(Composite parent) { final Composite contents = new Composite(parent, SWT.NONE); contents.setLayout(new GridLayout(1, false)); contents.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); createBoundWidgetWithLabel(contents, BgcBaseText.class, SWT.NONE, "Title", new String[0], email, "title", new NonEmptyStringValidator( "Please enter a title")); BgcBaseText descText = (BgcBaseText) createBoundWidgetWithLabel( contents, BgcBaseText.class, SWT.MULTI, "Description", new String[0], email, "description", new NonEmptyStringValidator( "Please enter at least a very small comment")); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = 200; descText.setLayoutData(gd); Label attLabel = widgetCreator.createLabel(contents, "Attachments"); attLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); final Composite attachmentsComposite = new Composite(contents, SWT.NONE); GridLayout layout = new GridLayout(1, false); layout.horizontalSpacing = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; attachmentsComposite.setLayout(layout); gd = new GridData(); gd.horizontalAlignment = SWT.FILL; attachmentsComposite.setLayoutData(gd); Button addButton = new Button(contents, SWT.PUSH); addButton.setImage(BgcPlugin.getDefault().getImageRegistry() .get(BgcPlugin.IMG_ADD)); addButton .setToolTipText("Add attachment"); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { AttachmentComposite attachmentComposite = new AttachmentComposite( attachmentsComposite, contents); contents.layout(true, true); Point shellSize = getShell().getSize(); getShell().setSize(shellSize.x, shellSize.y + attachmentComposite.getHeight()); attachments.add(attachmentComposite); } }); } @Override protected String getDialogShellTitle() { return "Send Error EMail"; } // private int createAttachmentChooser(Composite parent, // final Composite globalComposite) { // final Composite attachmentLine = new Composite(parent, SWT.NONE); // GridLayout layout = new GridLayout(3, false); // layout.horizontalSpacing = 0; // layout.marginWidth = 0; // layout.verticalSpacing = 0; // attachmentLine.setLayout(layout); // GridData gd = new GridData(); // gd.horizontalAlignment = SWT.FILL; // gd.grabExcessHorizontalSpace = true; // attachmentLine.setLayoutData(gd); // // final BiobankText attachmentText = (BiobankText) widgetCreator // .createWidget(attachmentLine, BiobankText.class, SWT.READ_ONLY, // null); // final Button button = new Button(attachmentLine, SWT.PUSH); // button.setText("Browse"); // button.addSelectionListener(new SelectionAdapter() { // @Override // public void widgetSelected(SelectionEvent e) { // FileDialog fd = new FileDialog(button.getShell(), SWT.OPEN); // fd.setText("Select attachment"); // String selected = fd.open(); // if (selected != null) { // attachments.add(selected); // attachmentText.setText(selected); // } // } // }); // Button removeButton = new Button(attachmentLine, SWT.PUSH); // removeButton.setImage(BioBankPlugin.getDefault().getImageRegistry() // .get(BgcPlugin.IMG_DELETE)); // removeButton.setToolTipText("Remove this attachment"); // removeButton.addSelectionListener(new SelectionAdapter() { // @Override // public void widgetSelected(SelectionEvent e) { // int height = attachmentLine.computeSize(SWT.DEFAULT, // SWT.DEFAULT).y; // attachments.remove(attachmentText.getText()); // attachmentText.setText(""); // attachmentLine.dispose(); // globalComposite.layout(true, true); // Point shellSize = getShell().getSize(); // getShell().setSize(shellSize.x, shellSize.y - height); // } // }); // return attachmentLine.computeSize(SWT.DEFAULT, SWT.DEFAULT).y; // } @Override protected void okPressed() { try { sendMail(); } catch (Exception e) { BgcPlugin.openAsyncError( "Error sending mail", e); } super.okPressed(); } private void initEmailDescriptor() { IPreferenceStore node = BiobankPlugin.getDefault().getPreferenceStore(); email = new EMailDescriptor(); email.setSmtpServer(node .getString(PreferenceConstants.ISSUE_TRACKER_SMTP_SERVER)); email.setServerPort(node .getString(PreferenceConstants.ISSUE_TRACKER_SMTP_SERVER_PORT)); email.setReceiverEmail(node .getString(PreferenceConstants.ISSUE_TRACKER_EMAIL)); email.setServerUsername(node .getString(PreferenceConstants.ISSUE_TRACKER_SMTP_SERVER_USER)); email.setServerPassword(node .getString(PreferenceConstants.ISSUE_TRACKER_SMTP_SERVER_PASSWORD)); } private void sendMail() throws Exception { IRunnableContext context = new ProgressMonitorDialog(Display .getDefault().getActiveShell()); context.run(true, false, new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) { monitor.beginTask("Sending mail...", IProgressMonitor.UNKNOWN); try { Properties props = new Properties(); props.put(MAIL_SMTP_HOST_KEY, email.getSmtpServer()); props.put(MAIL_SMTP_AUTH_KEY, Boolean.TRUE.toString()); // props.put("mail.debug", "true"); props.put(MAIL_SMTP_PORT_KEY, email.getServerPort()); props.put(MAIL_SMTP_SOCKET_FACTORY_PORT_KEY, email.getServerPort()); props.put(MAIL_SMTP_SOCKET_FACTORY_CLASS_KEY, SSL_FACTORY); props.put(MAIL_SMTP_SOCKET_FACTORY_FALLBACK_KEY, Boolean.FALSE.toString()); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(email .getServerUsername(), email .getServerPassword()); } }); // session.setDebug(true); Transport.send(getEmailMessage(session)); monitor.done(); } catch (AuthenticationFailedException afe) { BgcPlugin .openAsyncError( "Authentification Error", NLS.bind( "Wrong authentification for {0}", email.getServerUsername())); monitor.setCanceled(true); return; } catch (Exception e) { BgcPlugin.openAsyncError( "Error sending mail", e); monitor.setCanceled(true); return; } } }); } private Message getEmailMessage(Session session) throws Exception { MimeMessage message = new MimeMessage(session); message.setSubject(email.getTitle()); message.setContent(email.getDescription(), CONTENT_TYPE); message.setRecipient(Message.RecipientType.TO, new InternetAddress( email.getReceiverEmail())); Multipart mp = new MimeMultipart(); // create and fill the first message part MimeBodyPart mbp1 = new MimeBodyPart(); String text = email.getDescription() + "\n\n------"; if (SessionManager.getInstance().isConnected()) { text += "\nCreated by user " + SessionManager.getInstance().getSession().getUser() .getLogin(); } text += "\nSent from BioBank Java Client, version " + BiobankPlugin.getDefault().getBundle().getVersion(); mbp1.setText(text); mp.addBodyPart(mbp1); // add log file File logFile = Platform.getLogFileLocation().toFile(); addAttachment(mp, logFile.getPath()); // add user attachments for (AttachmentComposite attachment : attachments) { addAttachment(mp, attachment.getFile()); } // add the Multipart to the message message.setContent(mp); // set the Date: header message.setSentDate(new Date()); return message; } private void addAttachment(Multipart mp, String file) throws IOException, MessagingException { if (file != null && !file.isEmpty()) { // create the second message part MimeBodyPart mbp2 = new MimeBodyPart(); // attach the file to the message mbp2.attachFile(file); mp.addBodyPart(mbp2); } } private class AttachmentComposite extends BgcBaseWidget { private BgcBaseText attachmentText; private Button browseButton; private Button removeButton; private String file; public AttachmentComposite(Composite parent, final Composite globalComposite) { super(parent, SWT.NONE); GridLayout layout = new GridLayout(3, false); layout.horizontalSpacing = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; setLayout(layout); GridData gd = new GridData(); gd.horizontalAlignment = SWT.FILL; gd.grabExcessHorizontalSpace = true; setLayoutData(gd); attachmentText = (BgcBaseText) widgetCreator.createWidget(this, BgcBaseText.class, SWT.READ_ONLY, null); browseButton = new Button(this, SWT.PUSH); browseButton.setText("Browse"); browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog fd = new FileDialog(browseButton.getShell(), SWT.OPEN); fd.setText("Select attachment"); file = fd.open(); if (file != null) { attachmentText.setText(file); } } }); removeButton = new Button(this, SWT.PUSH); removeButton.setImage(BgcPlugin.getDefault().getImageRegistry() .get(BgcPlugin.IMG_DELETE)); removeButton .setToolTipText("Remove this attachment"); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int height = AttachmentComposite.this.computeSize( SWT.DEFAULT, SWT.DEFAULT).y; attachmentText.setText(""); AttachmentComposite.this.setVisible(false); GridData gd = (GridData) AttachmentComposite.this .getLayoutData(); gd.exclude = true; attachments.remove(AttachmentComposite.this); globalComposite.layout(true, true); Point shellSize = getShell().getSize(); getShell().setSize(shellSize.x, shellSize.y - height); AttachmentComposite.this.dispose(); } }); } public String getFile() { return file; } public int getHeight() { return computeSize(SWT.DEFAULT, SWT.DEFAULT).y; } } }